/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package etherblocks.engine.states;

import com.jme3.app.Application;
import com.jme3.app.state.AppStateManager;
import com.jme3.bounding.BoundingSphere;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Spatial;
import com.jme3.scene.VertexBuffer;
import com.jme3.scene.shape.Sphere;
import com.jme3.util.BufferUtils;

/**
 *
 * @author Carl
 */
public class SkyAppState extends BaseAppState{

    public SkyAppState(){
        
    }
    public static final Quaternion PITCH090 = new Quaternion().fromAngleAxis(FastMath.PI / 2, new Vector3f(1, 0, 0));
    private int sphereSamples = 10;
    private Geometry skySphereGeometry;
    private Mesh skySphereMesh;
    private float elapsedTime;
    private int timeFactor = 1;
    private VertexBuffer colorBuffer;
    private ColorRGBA startColorTop;
    private ColorRGBA startColorBottom;
    private ColorRGBA endColorTop;
    private ColorRGBA endColorBottom;
    private float animationDuration;
    private boolean animationEnabled = true;

    @Override
    public void initialize(AppStateManager stateManager, Application application){
        super.initialize(stateManager, application);
        skySphereMesh = new Sphere(sphereSamples, sphereSamples, mainApplication.getCamera().getFrustumFar(), false, true);
        skySphereMesh.setBuffer(VertexBuffer.Type.Color, 4, generateVertexColors());
        colorBuffer = skySphereMesh.getBuffer(VertexBuffer.Type.Color);
        skySphereGeometry = new Geometry("Sky", skySphereMesh);
        skySphereGeometry.setModelBound(new BoundingSphere(Float.POSITIVE_INFINITY, Vector3f.ZERO));
        Material material = new Material(mainApplication.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
        material.setBoolean("VertexColor", true);
        material.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off);
        //material.getAdditionalRenderState().setWireframe(true);
        skySphereGeometry.setMaterial(material);
        skySphereGeometry.setLocalRotation(PITCH090);
        skySphereGeometry.setQueueBucket(RenderQueue.Bucket.Sky);
        skySphereGeometry.setCullHint(Spatial.CullHint.Never);
        mainApplication.getRootNode().attachChild(skySphereGeometry);
    }

    @Override
    public void cleanup(){
        super.cleanup();
        mainApplication.getRootNode().detachChild(skySphereGeometry);
    }

    @Override
    public void update(float lastTimePerFrame){
        super.update(lastTimePerFrame);
        elapsedTime += (timeFactor * lastTimePerFrame);
        if(elapsedTime < 0){
            elapsedTime = 0;
            timeFactor = 1;
        }
        else if(elapsedTime > animationDuration){
            elapsedTime = animationDuration;
            timeFactor = -1;
        }
        skySphereGeometry.setLocalTranslation(mainApplication.getCamera().getLocation());
        if(animationEnabled){
            colorBuffer.updateData(BufferUtils.createFloatBuffer(generateVertexColors()));
            if((elapsedTime / animationDuration) > 1){
                animationEnabled = false;
            }
        }
    }

    private float[] generateVertexColors(){
        ColorRGBA color1 = new ColorRGBA(startColorTop);
        ColorRGBA color2 = new ColorRGBA(startColorBottom);
        color1.interpolate(endColorTop, (elapsedTime / animationDuration));
        color2.interpolate(endColorBottom, (elapsedTime / animationDuration));
        float[] colorArray = new float[skySphereMesh.getVertexCount() * 4];
        for (int i=0;i<skySphereMesh.getVertexCount();i++){
            float changeAmount = ((i-1) / sphereSamples) / ((float) sphereSamples);
            //The "first" vertex of the sphere has the second last index
            if(i == (skySphereMesh.getVertexCount() - 2)){
                changeAmount = 0;
            }
            //Earlier total interpolation
            changeAmount *= 1.75f;
            ColorRGBA color = new ColorRGBA(color1);
            color.interpolate(color2, changeAmount);
            colorArray[i * 4] = color.getRed();
            colorArray[(i * 4) + 1] = color.getGreen();
            colorArray[(i * 4) + 2] = color.getBlue();
            colorArray[(i * 4) + 3] = color.getAlpha();
        }
        return colorArray;
    }

    public void setAnimationDuration(float animationDuration){
        this.animationDuration = animationDuration;
    }
    
    public void setColors(ColorRGBA startColorTop, ColorRGBA startColorBottom, ColorRGBA endColorTop, ColorRGBA endColorBottom){
        this.startColorTop = startColorTop;
        this.startColorBottom = startColorBottom;
        this.endColorTop = endColorTop;
        this.endColorBottom = endColorBottom;
    }
}
